# coding=utf-8
import logging

from django.db import transaction
from rest_framework import serializers
from goods_info.models import GoodsModel, GoodsInventoryModel, AttachmentModel
from goods_info.serializer.units_serializer import UnitsSerializer
from goods_info.serializer.category_serializer import GoodsCategorySerializer
from goods_info.serializer.attachment_serializer import AttachmentSerializer
from MSB_ERP.utils.get_inventory import get_inventory

logger = logging.getLogger('erp')

class GoodsInventorySerializer(serializers.ModelSerializer):
    '''商品的库存 序列化器'''

    class Meta:
        model = GoodsInventoryModel
        fields = '__all__'

class GoodsBaseSerializer(serializers.ModelSerializer):
    '''新增和修改货品(商品)的序列化器'''

    # 商品对应的多个：商品库存对象，因为有很多个仓库
    # 在添加商品的库存中一并把商品的库存一起添加了
    inventory_list = GoodsInventorySerializer(many=True,required=True)

    class Meta:
        model = GoodsModel
        fields = '__all__'

    # 因为原先的create是添加库存和商品信息，而已一个商品有多个库存，所以原本的create他会添加多条数据库存信息，要进行重写函数的修改
    def create(self, validated_data):
        with transaction.atomic(): # 数据库事务（最灵活的），要不一起成功要不一起失败
            # 新增商品的，库存对象的列表
            # 这些就是商品的库存列表（一个商品有多个库存）
            item_list = validated_data.pop('inventory_list') # .pop是提取要哪个元素，取了之后该列表/字典就没有那个值了

            # 插入（纯粹的）商品信息，才会自动生成一个ID
            goods = GoodsModel.objects.create(**validated_data) # 将原先的数据进行了.pop的抽值之后，插入进数据库里面去

            for item in item_list:
                # 新建的时候，当前库存 = 初期库存
                item['cur_inventory'] = item.get('init_inventory',0)
                # 维护关联关系，告诉他是哪个货品
                # **item（**展开的意思）把其他的字段也一起添加进去
                GoodsInventoryModel.objects.create(goods=goods,**item)

        return goods

    def update(self, instance, validated_data):
        # 新增商品的，库存对象的列表
        # 这些就是商品的库存列表（一个商品有多个库存）
        # print(validated_data)
        item_list = validated_data.pop('inventory_list')  # .pop是提取要哪个元素，取了之后该列表/字典就没有那个值了
        # print(validated_data)
        with transaction.atomic(): # 数据库事务（最灵活的），要不一起成功要不一起失败
            for item in item_list: # 遍历每条库存的信息，并修改最高库存和最低库存
                GoodsInventoryModel.objects.filter(goods_id=instance.id,warehouse__name=item['warehouse_name']).update(
                    lowest_inventory = item.get('lowest_inventory',0),
                    highest_inventory = item.get('highest_inventory',0)
                )

            goods = super(GoodsBaseSerializer,self).update(instance=instance,validated_data=validated_data)
        return goods

class GoodsGetSerializer(serializers.ModelSerializer):
    '''
    商品查询的序列化器
    目标：
        1.把商品的单位--所有信息展示出来
        2.展示商品信息所属的商品类别 --所有信息展示出来
        3.展示商品的所有附件图片--所有图片信息展示出来
        4.展示商品的所有仓库中的库存信息
    '''

    # 基本单位名称（source：他会自动找到UnitsModel下的basic_name进行赋值）
    # 他除了传字段还可以传函数，但函数/字段一定要在模型类里面
    # units = serializers.CharField(source='basic_name')

    # 单位所有信息（对序列化器进行嵌套的操作）
    units = UnitsSerializer(read_only=True)
    # 商品类别
    category = GoodsCategorySerializer(read_only=True)

    # 商品类别名称（SerializerMethodField表示调用函数）
    images_list = serializers.SerializerMethodField(read_only=True)

    # 商品对应的多个：商品库存对象，因为有很多个仓库
    # 在添加商品的库存中一并把商品的库存一起添加了
    inventory_list = GoodsInventorySerializer(many=True, read_only=True)

    # 商品的当前的总库存数量
    cur_inventory = serializers.SerializerMethodField(read_only=True)
    class Meta:
        model = GoodsModel
        fields = '__all__'

    # 商品类别名称
    def get_images_list(self,obj):
        result = []
        if obj.images_list:
            # images_list属性是由多个附件的ID组成，中间使用逗号分割
            ids = obj.images_list.split(',')
            if ids:
                for i in ids:
                    # image是模型对象
                    image = AttachmentModel.objects.get(id=int(i))
                    # 附件的序列化器可以把附件的模型对象变成附件的字典
                    result.append(AttachmentSerializer(instance=image).data) # 把模型对象变成字典
            return result

    # 商品的当前的总库存数量
    def get_cur_inventory(self,obj):
        # 商品的当前的库存在很多地方需要看，所以最好写在公共模块里面去
        return get_inventory(obj.id)






